package com.ywk.base.javaBase.threadLocal;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * ThreadLocal即线程本地变量，并发场景下，会存在多个线程同时修改一个共享变量的场景。这就可能会出现线性安全问题。
 * 为了解决线性安全问题，可以用加锁的方式，比如使用`synchronized` 或者`Lock`。但是加锁的方式，可能会导致系统变慢。
 * 有另外一种方案，就是使用**空间换时间**的方式，即使用ThreadLocal。使用ThreadLocal类访问共享变量时，会在每个线程的本地，
 * 都保存一份共享变量的拷贝副本。多线程对共享变量修改时，实际上操作的是这个变量副本，从而保证线性安全。
 * https://blog.csdn.net/gongzi_9/article/details/126754648
 *
 * @Author zbh
 * @Date 2024/10/24
 */
public class ThreadLocalTest {

    private static final SimpleDateFormat s1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    private static final ThreadLocal<SimpleDateFormat> s2 = ThreadLocal.withInitial(()->new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));

    /**
     * 因为 s1 不是线性安全的，它以共享变量出现时，并发多线程场景下即会报错。
     */
    public static void f1(){
        ExecutorService threadPool = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            threadPool.execute(()->{
                try {
                    System.out.println(s1.parse("2022-07-24 16:34:30"));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            });
        }
        threadPool.shutdown();
    }

    public static void f2(){
        ExecutorService threadPool = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            threadPool.execute(()->{
                try {
                    System.out.println(s2.get().parse("2022-07-24 16:34:30"));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            });
        }
        threadPool.shutdown();
    }

    public static void main(String[] args) {
//        f1();
        f2();
    }

}
